/**
 * v8macros.h       Handful of macros that simplify your V8Class implementation and makes it 
 *                  look cleaner...
 *
 * Version:         1.0
 *
 * Copyright (c) Bal Bahadur Chettri
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided 
 * that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list of conditions and the 
 * following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list 
 * of conditions and the following disclaimer in the documentation and/or other materials provided with the 
 * distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Last Updated: Dec 10 2011
 */
#ifndef __V8MACROS_H
 #define __V8MACROS_H

#include "v8class.h"

/** Begins a v8 class declaration */
#define V8_DECLARE_CLASS(_N) \
class _N : public V8Class<_N> {

/** Ends a v8 class declaration */
#define V8_END_CLASS(_N) \
friend class V8Class<_N>; };

/** Implements the v8 class. You will usually invoke this macro in your source file. */
#define V8_IMPLEMENT_CLASS(_N) \
template<class _N> Persistent<ObjectTemplate> V8Class<_N>::_template;

/** Begins exposed methods declaration block */
#define V8_DECLARE_METHODS() \
static void _RegisterMethods() {

/** Ends method declaration block */
#define V8_END_METHODS() }

/** Begins exposed properties declaration block */
#define V8_DECLARE_PROPERTIES() \
static void _RegisterProperties() {

/** Ends property declaration block */
#define V8_END_PROPERTIES() }

/** Declares an exposed method */
#define V8_METHOD(_N) \
_template->Set(String::New(#_N), FunctionTemplate::New(_##_N));

/** Declares an exposed method with different callback function */
#define V8_METHOD_EX(_N,_C) \
_template->Set(String::New(#_N), FunctionTemplate::New(_C));

/** Declares an exposed property with getter only */
#define V8_PROPERTY_GET(_N) \
_template->SetAccessor(String::New(#_N), _##_N_getter, NULL);

/** Declares an exposed property with setter only */
#define V8_PROPERTY_SET(_N) \
_template->SetAccessor(String::New(#_N), NULL, _##_N_setter);

/** Declares an exposed property with both getter and setter */
#define V8_PROPERTY(_N) \
_template->SetAccessor(String::New(#_N), _##_N##_getter, _##_N##_setter);

/** Implements an export function to make the class exportable in some context.
 This should be placed within a public scope in the class declaration. 
 Default export name provided can be overidden when the class is actually exported. */
#define V8_IMPLEMENT_EXPORT(_SN) \
static void Export (Handle<ObjectTemplate> target, const char *name = NULL) { \
    target->Set ( \
        String::New(name ? name : _SN), \
        FunctionTemplate::New(_ctor), \
        ReadOnly ); \
}

/** Casts a v8 Object type to native C++ V8Cass type */
#define V8_CLASS_PTR(_T,_THIS) \
static_cast<_T *>(_THIS->GetPointerFromInternalField(0));

/** Implements the getter callback for the exposed property. This internally calls the actual
 Get_ method. */
#define V8_IMPLEMENT_PROPERTY_GET(_T,_N) \
static Handle<Value> _##_N##_getter (Local<String> prop, const AccessorInfo &info) { \
    _T *instance = V8_CLASS_PTR(_T,info.This()); \
    return instance->Get##_N(prop,info); \
}

/** Implements the seter callback for the exposed property. This internally calls the actual
 Set_ method. */
#define V8_IMPLEMENT_PROPERTY_SET(_T,_N) \
static void _##_N##_setter (Local<String> prop, Local<Value> value, const AccessorInfo &info) { \
    _T *instance = V8_CLASS_PTR(_T,info.This()); \
    instance->Set##_N(prop,value,info); \
}

/** Implements the getter and seter callbacks for the exposed property. This internally calls the
 actual Get_/Set_ property methods. */
#define V8_IMPLEMENT_PROPERTY(_T,_N) \
V8_IMPLEMENT_PROPERTY_GET(_T,_N) \
V8_IMPLEMENT_PROPERTY_SET(_T,_N)

/** Implements the callback for the exposed method. This internally calls the actual member fn. */
#define V8_IMPLEMENT_METHOD(_T,_N) \
static Handle<Value> _##_N (const Arguments &args) { \
    _T *instance = V8_CLASS_PTR(_T,args.This()); \
    return instance->_N(args); \
}

#endif /* __V8MACROS_H */
